<!DOCTYPE html>
<html lang="zh-CH" >
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="" />
	
	
	
	<title>Unity_ShaderGraph 节点之 Artistic Nodes ｜ zansimple</title>
	
    
    
    <meta name="description" content="注意 节点中很多输入为In(1)的其实是动态长度的Vector，可以接收Vector1~Vector4的值。
Adjustment 调整 Channel Mixer 根据输入的RGB值及各个通道的权重，输出权重加成后的RGB值。 比如：输入 RGB 为（0.5,0.6,0.7），假设输出 R 通道的比重设置为（0.1,0.2,0.3），则输出的 R 值为
0.5 * 0.1 &#43; 0.6 * 0.2 &#43; 0.7 * 0.3 = 0.249
_Node_OutRed = float3 (OutRedInRed, OutRedInGreen, OutRedInBlue);_Node_OutGreen = float3 (OutGreenInRed, OutGreenInGreen, OutGreenInBlue);_Node_OutBlue = float3 (OutBlueInRed, OutBlueInGreen, OutBlueInBlue);Out = float3(dot(In, _Node_OutRed), dot(In, _Node_OutGreen), dot(In, _Node_OutBlue)); Contrast 对比度调节 根据输入 In 及 Contrast 调节对比度。 Contrast 为1时输出 In , Contrast 为0时输出 In 的中值
float midpoint = pow(0." />
    

    

	
    
    <link rel="shortcut icon" href="https://lenzan.github.io/images/favicon.ico" />

    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/normalize.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.0/animate.min.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/zozo.css" />
	<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://lenzan.github.io/css/highlight.css" />

    
    
</head>

<body>
    <div class="main animate__animated animate__fadeInDown">
        <div class="nav_container animated fadeInDown">
    <div class="site_nav" id="site_nav">
        <ul>
            
            <li>
                <a href="/">首页</a>
            </li>
            
            <li>
                <a href="/">unity</a>
            </li>
            
            <li>
                <a href="/">归档</a>
            </li>
            
            <li>
                <a href="/">关于</a>
            </li>
            
        </ul>
    </div>
    <div class="menu_icon">
        <a id="menu_icon"><i class="ri-menu-line"></i></a>
    </div>
</div>
        <div class="header animated fadeInDown">
    <div class="site_title_container">
        <div class="site_title">
            <h1>
                <a href="https://lenzan.github.io/">
                    <span>zansimple</span>
                    <img src="https://lenzan.github.io/images/logo.svg" />
                </a>
            </h1>
        </div>
        <div class="description">
            <p class="sub_title">专注于Unity虚拟现实开发，游戏开发</p>
            <div class="my_socials">
                
                <a href="https://lenzan.github.io/index.xml" type="application/rss+xml" title="rss" target="_blank"><i
                        class="ri-rss-fill"></i></a>
            </div>
        </div>
    </div>
</div>
        <div class="content">
            <div class="post_page">
                <div class="post animate__animated animate__fadeInDown">
                    <div class="post_title post_detail_title">
                        <h2><a href='/posts/shadergraph/ShaderGraph-_Artistic-Nodes/'>Unity_ShaderGraph 节点之 Artistic Nodes</a></h2>
                        <span class="date">2018.08.24</span>
                    </div>
                    <div class="post_content markdown"><h3 id="注意">注意</h3>
<p>节点中很多输入为In(1)的其实是动态长度的Vector，可以接收Vector1~Vector4的值。</p>
<h3 id="adjustment-调整">Adjustment 调整</h3>
<h4 id="channel-mixer">Channel Mixer</h4>
<p>根据输入的RGB值及各个通道的权重，输出权重加成后的RGB值。 <br>
<img src="/img/shadergraph/Artistic/node1.png" alt="Channel"></p>
<p>比如：输入 RGB 为（0.5,0.6,0.7），假设输出 R 通道的比重设置为（0.1,0.2,0.3），则输出的 R 值为<br>
0.5 * 0.1 + 0.6 * 0.2 + 0.7 * 0.3 = 0.249<br>
<img src="/img/shadergraph/Artistic/node2.png" alt="Channel"></p>
<pre><code>_Node_OutRed = float3 (OutRedInRed, OutRedInGreen, OutRedInBlue);
_Node_OutGreen = float3 (OutGreenInRed, OutGreenInGreen, OutGreenInBlue);
_Node_OutBlue = float3 (OutBlueInRed, OutBlueInGreen, OutBlueInBlue);
Out = float3(dot(In, _Node_OutRed), dot(In, _Node_OutGreen), dot(In, _Node_OutBlue));
</code></pre>
<h4 id="contrast-对比度调节">Contrast 对比度调节</h4>
<p>根据输入 In 及 Contrast 调节对比度。 Contrast 为1时输出 In , Contrast 为0时输出 In 的中值<br>
<img src="/img/shadergraph/Artistic/node3.png" alt="Contrast"></p>
<pre><code>float midpoint = pow(0.5, 2.2);
Out =  (In - midpoint) * Contrast + midpoint;
</code></pre>
<h4 id="hue-色相调节">Hue 色相调节</h4>
<p>根据Offset调节色相。
可以根据Degrees调节即（-180，180）
或者根据Normalized调节即（-1，1）<br>
<img src="/img/shadergraph/Artistic/node4.png" alt="HUE"><br>
Degree代码（Normalized类似）：</p>
<pre><code>float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 P = lerp(float4(In.bg, K.wz), float4(In.gb, K.xy), step(In.b, In.g));
float4 Q = lerp(float4(P.xyw, In.r), float4(In.r, P.yzx), step(P.x, In.r));
float D = Q.x - min(Q.w, Q.y);
float E = 1e-10;
float3 hsv = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);

float hue = hsv.x + Offset / 360;
hsv.x = (hue &lt; 0)
        ? hue + 1
        : (hue &gt; 1)
            ? hue - 1
            : hue;

float4 K2 = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);
Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);
</code></pre>
<h4 id="invert-colors-颜色反转">Invert Colors 颜色反转</h4>
<p>可以选择单个或多个反转的通道<br>
<img src="/img/shadergraph/Artistic/node5.png" alt="Texture"></p>
<h4 id="replace-color-替换颜色">Replace Color 替换颜色</h4>
<p>In：输入的颜色<br>
From：要替换的颜色<br>
To：替换成的颜色<br>
Range：类似PS里的容差值<br>
Fuzziness：软化选区的边缘 <br>
<img src="/img/shadergraph/Artistic/node6.png" alt="Texture"></p>
<pre><code>float Distance = distance(From, In);
Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 1e-5f)));
</code></pre>
<h4 id="saturation-饱和度">Saturation 饱和度</h4>
<p>Saturation为1时输出原颜色，Saturation为0时为完全不饱和色。<br>
<img src="/img/shadergraph/Artistic/node7.png" alt="Texture"></p>
<pre><code>float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
Out =  luma.xxx + Saturation.xxx * (In - luma.xxx);
</code></pre>
<h4 id="white-balance-白平衡">White Balance 白平衡</h4>
<p>Temperature 让颜色变黄或者变蓝 <br>
Tint 让颜色变粉或者变绿<br>
<img src="/img/shadergraph/Artistic/node8.png" alt="Texture"></p>
<pre><code>// Range ~[-1.67;1.67] works best
float t1 = Temperature * 10 / 6;
float t2 = Tint * 10 / 6;

// Get the CIE xy chromaticity of the reference white point.
// Note: 0.31271 = x value on the D65 white point
float x = 0.31271 - t1 * (t1 &lt; 0 ? 0.1 : 0.05);
float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
float y = standardIlluminantY + t2 * 0.05;

// Calculate the coefficients in the LMS space.
float3 w1 = float3(0.949237, 1.03542, 1.08728); // D65 white point

// CIExyToLMS
float Y = 1;
float X = Y * x / y;
float Z = Y * (1 - x - y) / y;
float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
float3 w2 = float3(L, M, S);

float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);

float3x3 LIN_2_LMS_MAT = {
    3.90405e-1, 5.49941e-1, 8.92632e-3,
    7.08416e-2, 9.63172e-1, 1.35775e-3,
    2.31082e-2, 1.28021e-1, 9.36245e-1
};

float3x3 LMS_2_LIN_MAT = {
    2.85847e+0, -1.62879e+0, -2.48910e-2,
    -2.10182e-1,  1.15820e+0,  3.24281e-4,
    -4.18120e-2, -1.18169e-1,  1.06867e+0
};

float3 lms = mul(LIN_2_LMS_MAT, In);
lms *= balance;
Out = mul(LMS_2_LIN_MAT, lms);
</code></pre>
<h3 id="blend-混合">Blend 混合</h3>
<p>根据输入的Base、Blend两个值进行混合，Opacity可以设置混合的强度，0=不增强，Mode可以设置混合的模式。<br>
<img src="/img/shadergraph/Artistic/node9.png" alt="Texture">  <br>
不同Mode的Shader代码</p>
<ul>
<li>
<p>Burn</p>
<pre><code>  Out =  1.0 - (1.0 - Blend)/Base;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Darken</p>
<pre><code>  Out = min(Blend, Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Difference</p>
<pre><code>  Out = abs(Blend - Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Dodge</p>
<pre><code>  Out = Base / (1.0 - Blend);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Divide</p>
<pre><code>  Out = Base / (Blend + 0.000000000001);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Exclusion</p>
<pre><code>  Out = Blend + Base - (2.0 * Blend * Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>HardLight</p>
<pre><code>  float# result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
  float# result2 = 2.0 * Base * Blend;
  float# zeroOrOne = step(Blend, 0.5);
  Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>HardMix</p>
<pre><code>  Out = step(1 - Base, Blend);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Lighten</p>
<pre><code>  Out = max(Blend, Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>LinearBurn</p>
<pre><code>  Out = Base + Blend - 1.0;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>LinearDodge</p>
<pre><code>  Out = Base + Blend;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>LinearLight</p>
<pre><code>  Out = Blend &lt; 0.5 ? max(Base + (2 * Blend) - 1, 0) : min(Base + 2 * (Blend - 0.5), 1);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>LinearLightAddSub</p>
<pre><code>  Out = Blend + 2.0 * Base - 1.0;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Multiply</p>
<pre><code>  Out = Base * Blend;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Negation</p>
<pre><code>  Out = 1.0 - abs(1.0 - Blend - Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Screen</p>
<pre><code>  Out = 1.0 - (1.0 - Blend) * (1.0 - Base);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Overlay</p>
<pre><code>  float# result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
  float# result2 = 2.0 * Base * Blend;
  float# zeroOrOne = step(Base, 0.5);
  Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>PinLight</p>
<pre><code>  float# check = step (0.5, Blend);
  float# result1 = check * max(2.0 * (Base - 0.5), Blend);
  Out = result1 + (1.0 - check) * min(2.0 * Base, Blend);
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>SoftLight</p>
<pre><code>  float# result1 = 2.0 * Base * Blend + Base * Base * (1.0 - 2.0 * Blend);
  float# result2 = sqrt(Base) * (2.0 * Blend - 1.0) + 2.0 * Base * (1.0 - Blend);
  float# zeroOrOne = step(0.5, Blend);
  Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>VividLight</p>
<pre><code>  float# result1 = 1.0 - (1.0 - Blend) / (2.0 * Base);
  float# result2 = Blend / (2.0 * (1.0 - Base));
  float# zeroOrOne = step(0.5, Base);
  Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
<li>
<p>Subtract</p>
<pre><code>  Out = Base - Blend;
  Out = lerp(Base, Out, Opacity);
</code></pre>
</li>
</ul>
<h3 id="filter-滤镜">Filter 滤镜</h3>
<h4 id="dither">Dither</h4>
<p>Dither 是一种特定格式的噪波，用于随机量化误差。它用于防止大幅拉伸图片时出现的异常情况，如图像中的色带。Dither节点在屏幕空间抖动来确保图案的均匀分布。可以通过连接另一个节点来输入屏幕位置。此节点通常作为主节点上 Alpha Clip Threshold 的输入，为不透明对象提供透明的外观。这对于创建透明的对象很有用，而且仍然可以写入深度缓冲区。</p>
<p><img src="/img/shadergraph/Artistic/node10.png" alt="Texture"></p>
<pre><code>float2 uv = ScreenPosition.xy * _ScreenParams.xy;
float DITHER_THRESHOLDS[16] =
{
    1.0 / 17.0,  9.0 / 17.0,  3.0 / 17.0, 11.0 / 17.0,
    13.0 / 17.0,  5.0 / 17.0, 15.0 / 17.0,  7.0 / 17.0,
    4.0 / 17.0, 12.0 / 17.0,  2.0 / 17.0, 10.0 / 17.0,
    16.0 / 17.0,  8.0 / 17.0, 14.0 / 17.0,  6.0 / 17.0
};
uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
Out = In - DITHER_THRESHOLDS[index];
</code></pre>
<h3 id="mask-遮罩">Mask 遮罩</h3>
<h4 id="channel-mask">Channel Mask</h4>
<p>可以从下拉框中选择输出的通道。可以用来过滤或使用某个或某几个通道。<br>
<img src="/img/shadergraph/Artistic/node11.png" alt="Texture"></p>
<h4 id="color-mask">Color Mask</h4>
<p>从输入颜色与Mask Color相等的颜色的位置创建一个遮罩。<br>
Range：类似PS里的容差值<br>
Fuzziness：软化选区的边缘</p>
<p><img src="/img/shadergraph/Artistic/node12.png" alt="Texture"></p>
<pre><code>float Distance = distance(MaskColor, In);
Out = saturate(1 - (Distance - Range) / max(Fuzziness, 1e-5));
</code></pre>
<h3 id="normal-法线">Normal 法线</h3>
<h4 id="normal-blend-法线混合">Normal Blend 法线混合</h4>
<p>混合两个法线</p>
<p><img src="/img/shadergraph/Artistic/node13.png" alt="Texture"></p>
<pre><code>Out = normalize(float3(A.rg + B.rg, A.b * B.b));
</code></pre>
<h4 id="normal-create-创建法线">Normal Create 创建法线</h4>
<p>从一张高度图Texture创建法线贴图。UV和Sampler可以从对应的UV和Sampler State节点连接，如果没有设置将使用默认值。<br>
创建的法线贴图的强度可以用Offset和Strength属性修改。Offset定义了法线细节的最大距离，Strength是结果的系数。<br>
<img src="/img/shadergraph/Artistic/node14.png" alt="Texture"></p>
<pre><code>Offset = pow(Offset, 3) * 0.1;
float2 offsetU = float2(UV.x + Offset, UV.y);
float2 offsetV = float2(UV.x, UV.y + Offset);
float normalSample = Texture.Sample(Sampler, UV);
float uSample = Texture.Sample(Sampler, offsetU);
float vSample = Texture.Sample(Sampler, offsetV);
float3 va = float3(1, 0, (uSample - normalSample) * Strength);
float3 vb = float3(0, 1, (vSample - normalSample) * Strength);
Out = normalize(cross(va, vb));
</code></pre>
<h4 id="normal-strength">Normal Strength</h4>
<p>修改法线贴图的Strength。Strength为1时返回原图，为0时返回纯黑的法线贴图。  <br>
<img src="/img/shadergraph/Artistic/node15.png" alt="Texture"></p>
<pre><code>Out = {precision}3(In.rg * Strength, In.b);
</code></pre>
<h4 id="normal-unpack">Normal Unpack</h4>
<p>解包一个法线贴图。</p>
<ul>
<li>注意
通常这是多余的，因为在Sample的时候法线贴图的Type一般会设置为Normal，如下图所示，已经自动解包成法线贴图。可以看下面Normal Unpack节点是多余的，下面预览是相同的。<br>
<img src="/img/shadergraph/Artistic/node16.png" alt="Texture"></li>
</ul>
<h3 id="utility-工具">Utility 工具</h3>
<h4 id="colorspace-conversion-颜色空间转换">Colorspace Conversion 颜色空间转换</h4>
<p>从一种颜色空间转换到另一种颜色空间。<br>
<img src="/img/shadergraph/Artistic/node17.png" alt="Texture"></p>
</div>
                    <div class="post_footer">
                        
                        <div class="meta">
                            <div class="info">
                                <span class="field tags">
                                    <i class="ri-stack-line"></i>
                                    
                                    <a href="https://lenzan.github.io/tags/Unity3DShader/">Unity3D，Shader</a>
                                    
                                    <a href="https://lenzan.github.io/tags/ShaderGraph/">ShaderGraph</a>
                                    
                                </span>
                            </div>
                        </div>
                        
                    </div>
                </div>
                
                
            </div>
        </div>
    </div>
    <a id="back_to_top" href="#" class="back_to_top"><span>△</span></a>
    <footer class="footer">
    <div class="powered_by">
        <a href="https://varkai.com">Designed by VarKai,</a>
        <a href="http://www.gohugo.io/">Proudly published with Hugo</a>
    </div>

    <div class="footer_slogan">
        <span></span>
    </div>
</footer>
    <script src="https://lenzan.github.io/js/jquery-3.5.1.min.js"></script>
<link href="https://lenzan.github.io/css/fancybox.min.css" rel="stylesheet">
<script src="https://lenzan.github.io/js/fancybox.min.js"></script>
<script src="https://lenzan.github.io/js/zozo.js"></script>






</body>

</html>